﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Windows;
using System.Windows.Data;

namespace ValueConverters
{
	/// <summary>
	/// Converts a bool into a visibility (visible/hidden).
	/// </summary>

	[ValueConversion(typeof(bool), typeof(Visibility))]
	public class BooleanToVisibilityConverter : IValueConverter
	{
		public object Convert(object Value, Type TargetType, object Parameter, CultureInfo Culture)
		{
			bool TheValue = System.Convert.ToBoolean(Value, CultureInfo.InvariantCulture);
			string Params = System.Convert.ToString(Parameter, CultureInfo.InvariantCulture);
			Visibility ReturnValue;

			if (Params.ToLower().Contains("reversed")) { TheValue = !TheValue; }

			if (TheValue) { ReturnValue = Visibility.Visible; }
			else { ReturnValue = Visibility.Hidden; }

			return ReturnValue;
		}

		public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
		{
			return null;
		}
	}

	/// <summary>
	/// Converts a bool into a double.
	/// </summary>

	[ValueConversion(typeof(bool), typeof(double))]
	public class BooleanToDoubleConverter : IValueConverter
	{
		public object Convert(object Value, Type TargetType, object Parameter, CultureInfo Culture)
		{
			bool TheValue = System.Convert.ToBoolean(Value, CultureInfo.InvariantCulture);
			string Params = System.Convert.ToString(Parameter, CultureInfo.InvariantCulture);
			double FalseValue = 0;
			double TrueValue = 1;
			string[] OperationData;
			double OperationValue;

			foreach (string Operation in System.Convert.ToString(Parameter).Split(new char[] { ' ' }))
			{
				OperationData = Operation.Split('(');
				if (OperationData.Length == 2)
				{
					OperationData[1] = OperationData[1].Split(')')[0];

					if (Double.TryParse(OperationData[1], out OperationValue))
					{
						switch (OperationData[0].ToLower())
						{
							case "true":
								TrueValue = OperationValue;
								break;
							case "false":
								FalseValue = OperationValue;
								break;
						}
					}
				}
			}

			if (TheValue) { return TrueValue; }
			else { return FalseValue; }
		}

		public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
		{
			return null;
		}
	}


	/// <summary>
	/// Performs a series of simple math operations.
	/// </summary>

	[ValueConversion(typeof(double), typeof(double))]
	public class SimpleMathDouble : IValueConverter
	{
		public object Convert(object Value, Type TargetType, object Parameter, CultureInfo Culture)
		{
			// A valid parameter looks something like this:
			// "add(1) multiply(2) max(10)"
			// Each operation becomes an item in the Operations array.
			string[] Operations;
			double ReturnValue = System.Convert.ToDouble(Value);

			Operations = System.Convert.ToString(Parameter).Split(new char[] { ' ' });
			foreach (string Operation in Operations)
			{
				ReturnValue = PerformOperation(ReturnValue, Operation);
			}
			return ReturnValue;
		}

		public object ConvertBack(object Value, Type TargetType, object Parameter, CultureInfo Culture)
		{
			return null;
		}

		private double PerformOperation(double InputValue, string Operation)
		{
			// Valid operation data is [Operation type][Operation value].
			string[] OperationData;
			double OperationValue = 0;
			double ReturnValue = InputValue;

			OperationData = Operation.Split('(');
			if (OperationData.Length == 2)
			{
				OperationData[1] = OperationData[1].Split(')')[0];

				if (Double.TryParse(OperationData[1], out OperationValue))
				{
					switch (OperationData[0].ToLower())
					{
						case "add":
							ReturnValue = OperationValue + ReturnValue;
							break;
						case "sub":
							ReturnValue = ReturnValue - OperationValue;
							break;
						case "subfrom":
							ReturnValue = OperationValue - ReturnValue;
							break;
						case "mult":
							ReturnValue = OperationValue * ReturnValue;
							break;
						case "div":
							if (ReturnValue != 0) { ReturnValue = OperationValue / ReturnValue; }
							break;
						case "divby":
							if (OperationValue != 0) { ReturnValue = ReturnValue / OperationValue; }
							break;
						case "min":
							if (ReturnValue < OperationValue) { ReturnValue = OperationValue; }
							break;
						case "max":
							if (ReturnValue > OperationValue) { ReturnValue = OperationValue; }
							break;
					}
				}
			}

			return ReturnValue;
		}

	}
}